import java.awt.*;

// This class represents celestial bodies like stars, planets, asteroids, etc..
public class CelestialBody {

    private String name;
    private double mass;
    private double radius;
    private Vector3 position; // position of the center.
    private Vector3 currentMovement;
    private Color color; // for drawing the body.

    // initialization constructor
    public CelestialBody(String name, double mass, double radius,
                         Vector3 position, Vector3 currentMovement,
                         Color color) {
        this.name            = name;
        this.mass            = mass;
        this.radius          = radius;
        this.position        = position;
        this.currentMovement = currentMovement;
        this.color           = color;
    }

    // Returns the distance between this celestial body and the specified 'body'.
    public double distanceTo(CelestialBody body) {
        return this.position.distanceTo(body.position);
    }

    // Returns a vector representing the gravitational force exerted by 'body' on this celestial body.
    public Vector3 gravitationalForce(CelestialBody body) {
        Vector3 direction = body.position.minus(this.position);
        double r = direction.length();
        direction.normalize();
        double force = Simulation.G * this.mass * body.mass / (r*r);
        return direction.times(force);
    }

    /**
     * displaces this body by considering a vector 'force' that is exerted
     * on it, in addition to already existing forces (movement)
     * (force is dependent on mass)
     * (updates position as the sum of position, force and movement)
     * (updates position as the difference of previous and new position)
     * @param force a vector representing the force that acts on this body
     */
    public void move(Vector3 force) {
        // F = m*a -> a = F/m
        double acceleration = 1 / this.mass;

        // displace position
        Vector3 newPosition = this.position.plus(force.times(acceleration)).plus(this.currentMovement);

        // displace movement: current -> (new - old) position
        Vector3 newMovement = newPosition.minus(this.position);

        this.position = newPosition;
        this.currentMovement = newMovement;
    }

    /**
     * returns a string containing information of this celestial body, which
     * is to say { name, mass, radius, position and currentMovement } in the
     * following form:
     * "Earth, 5.972E24 kg, radius: 6371000.0 m, position: [1.48E11,0.0,0.0] m, movement: [0.0,29290.0,0.0] m/s."
     * @return formatted string
     */
    @Override
    public String toString() {
        return String.format("%s, %g kg, radius: %g m, position: %s m, movement: %s m/s",
                name,
                mass,
                radius,
                position,
                currentMovement);
    }

    /**
     * prints this celestial body to StdOut without a newline, in the format
     * specified by the toString directive
     */
    public void print() {
        System.out.print(this);
    }

    /**
     * draws this celestial body to a StdDraw canvas as a dot using a
     * color previously assigned to this body
     * (radius of the dot is in relation to the radius of the celestial body)
     */
    public void draw() {
        // use log10 due to large variation of radii
        this.position.drawAsDot(1e9d * Math.log10(this.radius), this.color);
    }

}

